package cn.tedu.store.portal.webapi.service.impl;


import cn.tedu.store.commons.pojo.portal.entity.PortalCategoryEntity;
import cn.tedu.store.commons.pojo.portal.vo.HomeElementsVO;
import cn.tedu.store.commons.pojo.portal.vo.PortalCategoryTreeVO;
import cn.tedu.store.commons.pojo.portal.vo.ProductDetailVO;
import cn.tedu.store.commons.pojo.product.vo.*;
import cn.tedu.store.commons.web.JsonPage;
import cn.tedu.store.portal.service.IHomeElementService;
import cn.tedu.store.product.service.*;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class HomeElementServiceImpl implements IHomeElementService {

    @DubboReference
    private IHomeAdvertiseService homeAdvertiseService;
    @DubboReference
    private IBrandService brandService;
    @DubboReference
    private ISpuService spuService;
    @DubboReference
    private ICategoryService categoryService;
    @DubboReference
    private ISkuService skuService;
    @DubboReference
    private IAttributeService attributeService;

    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;

    public static final String CATEGORY_TREE_KEY = "category-tree";

    @Override
    public HomeElementsVO getItem() {
        log.debug("开始处理[获取首页信息]业务");
        HomeElementsVO homeElementsVO = new HomeElementsVO();
        //轮播图列表
        homeElementsVO.setHomeAdvertises(homeAdvertiseService.list());
        //推荐品牌列表
        homeElementsVO.setHomeBrands(brandService.recommendList(1, 5).getList());
        //新品推荐列表
        homeElementsVO.setHomeNewProducts(spuService.newProductList(1,10).getList());
        //自定义推荐商品列表
        homeElementsVO.setHomeRecommendProducts(spuService.recommendList(1,10).getList());
        return homeElementsVO;
    }

    @Override
    public List<CategoryListItemVO> navbarCategory() {
        return categoryService.portalList();
    }

    @Override
    public JsonPage<BrandListItemVO> brandList(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        return brandService.list(pageNum,pageSize);
    }

    @Override
    public JsonPage<CategoryListItemVO> subCategory(Long parentId, Integer pageNum, Integer pageSize) {
        return categoryService.listByParentId(parentId, pageNum, pageSize);
    }

/*    @Override
    public PortalCategoryTreeVO<PortalCategoryEntity> categoryTree() {
        log.debug("获取前台分类树");
        if(redisTemplate.hasKey(CATEGORY_TREE_KEY)){
            return (PortalCategoryTreeVO<PortalCategoryEntity>) redisTemplate.opsForValue().get(CATEGORY_TREE_KEY);
        }
        //若Redis中没有分类树数据
        List<CategoryListItemVO> categoryListItemVOs = categoryService.list(1,0).getList();
        log.debug("获取到{}条分类数据",categoryListItemVOs.size());
        PortalCategoryTreeVO<PortalCategoryEntity> categoryTree =
                initTree(categoryListItemVOs);
        redisTemplate.boundValueOps(CATEGORY_TREE_KEY).set(categoryTree);
        return categoryTree;
    }

    private PortalCategoryTreeVO<PortalCategoryEntity> initTree(List<CategoryListItemVO> categoryListItemVOs) {
        Map<Long,List<PortalCategoryEntity>> map = new HashMap<>();
        for (CategoryListItemVO categoryListItemVO : categoryListItemVOs) {
            PortalCategoryEntity portalCategoryEntity = new PortalCategoryEntity();
            BeanUtils.copyProperties(categoryListItemVO,portalCategoryEntity);
            long parentId = portalCategoryEntity.getParentId();
            if(map.containsKey(parentId)){
                map.get(parentId).add(portalCategoryEntity);
            }else {
                List<PortalCategoryEntity> list = new ArrayList<>();
                list.add(portalCategoryEntity);
                map.put(parentId,list);
            }
        }
        //遍历map并将各分类组合成categoryTree三级分类树
        List<PortalCategoryEntity> firstLevels = map.get(0L);//获取所有一级分类
        if(firstLevels == null || firstLevels.isEmpty()){
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"不存一级分类");
        }
        for (PortalCategoryEntity firstLevel : firstLevels) {
            //获取二级分类的父类id(map中二级分类的key)
            Long secondLevelParentId = firstLevel.getId();
            List<PortalCategoryEntity> secondLevels = map.get(secondLevelParentId);//获取二级分类
            if(secondLevels == null || secondLevels.isEmpty()){
                log.warn("此一级分类不存在二级分类!");
                continue;
            }
            for (PortalCategoryEntity secondLevel : secondLevels) {
                //获取三级分类的父类id(map中三级分类的key)
                Long thirdLevelParentId = secondLevel.getId();
                List<PortalCategoryEntity> thirdLevels = map.get(thirdLevelParentId);
                if(secondLevels == null || secondLevels.isEmpty()){
                    log.warn("此二级分类不存在三级分类!");
                    continue;
                }
                secondLevel.setChildren(thirdLevels);
            }
            firstLevel.setChildren(secondLevels);
        }
        PortalCategoryTreeVO<PortalCategoryEntity> treeVO = new PortalCategoryTreeVO<>();
        treeVO.setCategories(firstLevels);
        return treeVO;
    }*/

    /**
     * 多级分类递归实现
     * @return 分类树
     */
    @Override
    public PortalCategoryTreeVO<PortalCategoryEntity> categoryTree() {
        log.debug("获取前台分类树");
        if(redisTemplate.hasKey(CATEGORY_TREE_KEY)){
            return (PortalCategoryTreeVO<PortalCategoryEntity>) redisTemplate.opsForValue().get(CATEGORY_TREE_KEY);
        }
        //若Redis中没有分类树数据
        List<CategoryListItemVO> categoryListItemVOs = categoryService.list(1,0).getList();
        log.debug("获取到{}条分类数据",categoryListItemVOs.size());
        //查找数据库中的分类数据
        PortalCategoryTreeVO<PortalCategoryEntity> categoryTreeVO = new PortalCategoryTreeVO<>();
        List<PortalCategoryEntity> temp = new ArrayList<>();
        for (CategoryListItemVO categoryListItemVO : categoryListItemVOs) {
            PortalCategoryEntity portalCategoryEntity = new PortalCategoryEntity();
            BeanUtils.copyProperties(categoryListItemVO,portalCategoryEntity);
            temp.add(portalCategoryEntity);
        }
        List<PortalCategoryEntity> list = temp.stream().filter(category -> category.getParentId() == 0)
                .map((menu) -> {
                    menu.setChildren(getChildren(menu, temp));
                    return menu;
                }).collect(Collectors.toList());
        categoryTreeVO.setCategories(list);
        redisTemplate.boundValueOps(CATEGORY_TREE_KEY).set(categoryTreeVO,1, TimeUnit.MINUTES);
        return categoryTreeVO;
    }

    //查找所有子类并组装
    private List<PortalCategoryEntity> getChildren(PortalCategoryEntity root, List<PortalCategoryEntity> all) {
        List<PortalCategoryEntity> children = all.stream().filter(category -> category.getParentId().equals(root.getId()))
                .map(menu -> {
                    menu.setChildren(getChildren(menu, all));
                    return menu;
                }).collect(Collectors.toList());
        return children;
    }

    @Override
    public JsonPage<SpuListItemVO> productList(Integer pageNum, Integer pageSize) {
        return spuService.portalList(pageNum,pageSize);
    }

    @Override
    public JsonPage<SpuListItemVO> productListByBrand(Long brandId, Integer pageNum, Integer pageSize) {
        return spuService.listByBrand(brandId, pageNum,pageSize);
    }

    @Override
    public JsonPage<SpuListItemVO> productListByCategory(Long categoryId, Integer pageNum, Integer pageSize) {
        return spuService.listByCategory(categoryId, pageNum,pageSize);
    }

    @Override
    public ProductDetailVO getDetailById(Long id) {
        return spuService.getPortalDetailById(id);
    }

    @Override
    public List<SkuListItemVO> getSkuBySpuId(Long spuId) {
        return skuService.list(spuId);
    }

    @Override
    public List<AttributeListItemVO> getAttributeBySpuId(Long spuId) {
        return attributeService.listBySpuId(spuId);
    }


}
